package service

import (
	"context"
	"encoding/json"
	"fmt"
	"gitee.com/shuokeyun/api-gateway/internal/biz"
	v1 "gitee.com/shuokeyun/apis/merchant-service/api/v1"
	"github.com/go-kratos/kratos/v2/metadata"
	"github.com/go-kratos/kratos/v2/transport/http"
	"net/url"
	"strconv"
	"strings"
	"time"
)

type ApiGateway struct {
	proxy *biz.Proxy
	auth  v1.UserAuthClient
}

func NewApiGateway(proxy *biz.Proxy, auth v1.UserAuthClient) *ApiGateway {
	return &ApiGateway{
		proxy: proxy,
		auth:  auth,
	}
}

func (a *ApiGateway) Handler(hc http.Context) error {
	vars := hc.Vars()
	serviceName, symbol := parseUrl(vars)
	if serviceName == "" || symbol == "" {
		hc.Response().WriteHeader(404)
		return nil
	}
	token, app := hc.Header().Get("Token"), hc.Header().Get("App-Id")
	appId, err := strconv.Atoi(app)
	if err != nil || appId == 0 || token == "" {
		hc.Response().WriteHeader(401)
		return nil
	}
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	reply, err := a.auth.CheckLogin(ctx, &v1.CheckLoginRequest{
		Token: token,
		AppId: int32(appId),
	})
	if err != nil {
		return err
	}
	ctx = metadata.AppendToClientContext(ctx, "x-md-global-am-id", strconv.Itoa(int(reply.MerchantId)))
	ctx = metadata.AppendToClientContext(ctx, "x-md-global-am-uid", strconv.Itoa(int(reply.Id)))
	ctx = metadata.AppendToClientContext(ctx, "x-md-global-app-id", app)
	ctx = metadata.AppendToClientContext(ctx, "x-md-global-price-area", strconv.Itoa(int(reply.PriceArea)))

	res, err := a.proxy.Forward(serviceName, symbol, hc.Request().Body)

	if err != nil {
		return err
	}
	by, _ := json.Marshal(res)
	hc.Response().Write(by)
	return nil
}

func parseUrl(vars url.Values) (string, string) {
	bff, service, method, version := vars.Get("bff"), vars.Get("service"), vars.Get("method"), vars.Get("version")
	if version == "" {
		version = "v1"
	}
	if bff == "" || service == "" || method == "" || version == "" {
		return "", ""
	}
	li := strings.Split(method, "-")
	for k, v := range li {
		li[k] = strings.ToUpper(string(v[0])) + v[1:]
	}
	method = strings.Join(li, "")
	service = strings.ToUpper(string(service[0])) + service[1:]
	serviceName := fmt.Sprintf("shuokeyun.%s_bff.api.%s.%s", bff, version, service)
	symbol := fmt.Sprintf("shuokeyun.%s_bff.api.%s.%s/%s", bff, version, service, method)
	return serviceName, symbol
}
